package com.hexinfo.dmpro.admin.service;

import cn.hutool.core.util.ObjectUtil;
import com.hexinfo.dmpro.common.base.BaseService;
import com.hexinfo.dmpro.common.base.Page;
import com.hexinfo.dmpro.common.base.PageResult;
import com.hexinfo.dmpro.admin.dao.RoleMapper;
import com.hexinfo.dmpro.admin.dao.UserAvatarMapper;
import com.hexinfo.dmpro.admin.dao.UserMapper;
import com.hexinfo.dmpro.common.exception.BadRequestException;
import com.hexinfo.dmpro.common.exception.EntityExistException;
import com.hexinfo.dmpro.admin.model.Role;
import com.hexinfo.dmpro.admin.model.User;
import com.hexinfo.dmpro.admin.model.UserAvatar;
import com.hexinfo.dmpro.admin.model.UserRole;
import com.hexinfo.dmpro.admin.model.req.UserRequest;
import com.hexinfo.dmpro.common.utils.FileUtil;
import com.hexinfo.dmpro.common.utils.SecurityUtils;
import com.hexinfo.dmpro.common.utils.StringUtils;
import com.hexinfo.dmpro.common.utils.ValidationUtil;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName UserService
 * @Describe
 * @Author ml.wang
 * @Date 2021-06-17
 */
@Slf4j
@Service
@CacheConfig(cacheNames = "user")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserService extends BaseService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserAvatarMapper userAvatarMapper;

    @Value("${file.avatar}")
    private String avatar;

    public PageResult queryAll(UserRequest userRequest, Page page) {
        return selectPage(userMapper, "queryAll", page, userRequest);
    }

    public List<User> selectAll() {
        return userMapper.selectAll();
    }

    public PageResult queryAllByProjectId(Long projectId, UserRequest userRequest, Page page) {
        return selectPage(userMapper, "queryAllByProjectId", page, projectId, userRequest);
    }

    public List<User> queryProjectManagerForMembers(Long projectId) {
        return userMapper.getProjectManagerForMemebers(projectId);
    }

    public List<User> queryProjectDeveloperForMembers(Long projectId) {
        return userMapper.getProjectDeveloperForMemebers(projectId);
    }

    public List<User> selectAllProjectManager() {
        return userMapper.selectAllProjectManager();
    }

    public List<User> selectAllProjectDeveloper() {
        return userMapper.selectAllProjectDeveloper();
    }

    //中间表查询roleId
    public List<Integer> selectByUserId(Long id){

        return userMapper.findRoleIdByUserId(id);
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void create(User resource) {
        if (userMapper.findByName(resource.getUsername()) != null) {
            throw new EntityExistException(User.class, "username", resource.getUsername());
        }
        // email 更改为非必填后，该判断不再需要
        // if (userMapper.findByEmail(resource.getEmail()) != null) {
        //    throw new EntityExistException(User.class, "email", resource.getEmail());
        // }
        resource.setCreateTime(new Timestamp(new Date().getTime()));
        // 插入user信息
        userMapper.save(resource);
        // 插入user-role关系信息
        if (resource.getRoles() != null && resource.getRoles().size() != 0) {
            resource.getRoles().forEach(roles -> {
                UserRole userRole = new UserRole();
                userRole.setUserId(resource.getId());
                userRole.setRoleId(roles.getId());
                userMapper.saveRoles(userRole);
            });
        }
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void update(User resource) {
        User user = userMapper.findById(resource.getId());
        ValidationUtil.isNull(user.getId(), "User", "id", resource.getId());
        user = userMapper.findByName(resource.getUsername());
        if (user != null && !user.getId().equals(resource.getId())) {
            throw new EntityExistException(User.class, "username", resource.getUsername());
        }
//        user = userMapper.findByEmail(resource.getEmail());
//        if (user != null && !user.getId().equals(resource.getId())) {
//            throw new EntityExistException(User.class, "email", resource.getEmail());
//        }
        // 更新user信息
        resource.setCreateTime(new Timestamp(new Date().getTime()));
        userMapper.modify(resource);
        // 删除 user-role 关系
        userMapper.untiedRolesByUserId(resource.getId());
        // 插入新的 user-role 关系
        if (resource.getRoles() != null && resource.getRoles().size() != 0) {
            resource.getRoles().forEach(roles -> {
                UserRole userRole = new UserRole();
                userRole.setUserId(resource.getId());
                userRole.setRoleId(roles.getId());
                userMapper.saveRoles(userRole);
            });
        }
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<Long> ids) {
        // 删除 user-role 关系
        userMapper.untiedRolesByUserIds(ids);
        // 删除 user
        userMapper.delete(ids);
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void updateCenter(User resource) {
        resource.setCreateTime(new Timestamp(new Date().getTime()));
        userMapper.modifyCenter(resource);
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void modifyPassword(Long id, String newPassword) {
        userMapper.modifyPassword(id, newPassword, new Date());
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void updateAvatar(MultipartFile multipartFile) {
        User user = userMapper.findByName(SecurityUtils.getUsername());
        UserAvatar userAvatar = user.getUserAvatar();
        String oldPath = "";
        if (userAvatar != null) {
            oldPath = userAvatar.getPath();
        }
        File file = FileUtil.upload(multipartFile, avatar);
        assert file != null;

        UserAvatar resultAvatar = new UserAvatar(userAvatar, file.getName(), file.getPath(), FileUtil.getSize(multipartFile.getSize()));
        resultAvatar.setCreateTime(new Timestamp(new Date().getTime()));
        // 插入头像信息到表中并返回主键id
        userAvatarMapper.save(resultAvatar);
        // 更新 用户表的 头像id 字段
        userMapper.modifyAvatar(user.getId(), resultAvatar.getId());
        // 删除原先头像
        if (StringUtils.isNotBlank(oldPath)) {
            FileUtil.del(oldPath);
        }
    }

    public User findByName(String username) {
        return userMapper.findByName(username);
    }

    public boolean existUsername(String username) {
        User user = findByName(username);
        return ObjectUtil.isEmpty(user);
    }

    /**
     * 如果当前用户的角色级别低于创建用户的角色级别，则抛出权限不足的错误
     */
    public void checkLevel(User resources) {
        User user = this.findByName(SecurityUtils.getUsername());
        Integer currentLevel = Collections.min(roleMapper.findByUserId(user.getId()).stream().map(Role::getLevel).collect(Collectors.toList()));
        Integer optLevel = Collections.min(roleMapper.findByRoles(resources.getRoles()).stream().map(Role::getLevel).collect(Collectors.toList()));
        if (currentLevel > optLevel) {
            throw new BadRequestException("角色权限不足");
        }
    }

    public void checkLevel(User resource, Set<Long> ids) {
        for (Long id : ids) {
            try {
                Integer currentLevel = Collections.min(roleMapper.findByUserId(resource.getId()).stream().map(Role::getLevel).collect(Collectors.toList()));
                Integer optLevel = Collections.min(roleMapper.findByUserId(id).stream().map(Role::getLevel).collect(Collectors.toList()));
                if (currentLevel > optLevel) {
                    throw new BadRequestException("当前用户的角色权限不足，不能删除该用户");
                }
            } catch (NoSuchElementException e) {
                // 有可能角色不存在或者被删除这里汇报NoSuchElementException错误，所以这里出现NoSuchElementException则跳过。
                log.warn(e.getMessage());
            }
        }
    }

    /**
     * @Method getProjectManagerIsMemebers
     * @Param [projectId]
     * @Return java.util.List<com.hexinfo.autoflow.admin.model.User>
     * @Description 根据项目ID查询其下管理员用户
     * @Author gj.xu
     * @Date 2023/7/25 17:09
     * @Version V2.0
     */
    public List<User> getProjectManagerIsMemebers(Long projectId) {
        return userMapper.getProjectManagerIsMemebers(projectId);
    }
}
